﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TomanuExtensions.Utils;

namespace AmiEmuLib.AmigaMachine.AmigaCPU
{
    internal static class CCRRegistry
    {
        public const int BIT_EXTEND = 4;
        public const int BIT_NEGATIVE = 3;
        public const int BIT_ZERO = 2;
        public const int BIT_OVERFLOW = 1;
        public const int BIT_CARRY = 0;

        public const ushort MASK_EXTEND = 1 << 4;
        public const ushort MASK_NEGATIVE = 1 << 3;
        public const ushort MASK_ZERO = 1 << 2;
        public const ushort MASK_OVERFLOW = 1 << 1;
        public const ushort MASK_CARRY = 1 << 0;

        /// <summary>
        /// Extend.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <returns></returns>
        public static bool IsExtend(ushort a_sr)
        {
            return Bits.IsSet(a_sr, BIT_EXTEND);
        }

        /// <summary>
        /// Extend.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <param name="a_x"></param>
        /// <returns></returns>
        public static void SetExtend(ref ushort a_sr, bool a_bitValue)
        {
            Bits.SetBit(ref a_sr, BIT_EXTEND, a_bitValue);
        }

        /// <summary>
        /// Negative
        /// </summary>
        /// <param name="a_sr"></param>
        /// <returns></returns>
        public static bool IsNegative(ushort a_sr)
        {
            return Bits.IsSet(a_sr, BIT_NEGATIVE);
        }

        /// <summary>
        /// Negative
        /// </summary>
        /// <param name="a_sr"></param>
        /// <param name="a_bitValue"></param>
        public static void SetNegative(ref ushort a_sr, bool a_bitValue)
        {
            Bits.SetBit(ref a_sr, BIT_NEGATIVE, a_bitValue);
        }

        /// <summary>
        /// Zero.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <returns></returns>
        public static bool IsZero(ushort a_sr)
        {
            return Bits.IsSet(a_sr, BIT_ZERO);
        }

        /// <summary>
        /// Zero.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <param name="a_bitValue"></param>
        public static void SetZero(ref ushort a_sr, bool a_bitValue)
        {
            Bits.SetBit(ref a_sr, BIT_ZERO, a_bitValue);
        }

        /// <summary>
        /// Overflow.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <returns></returns>
        public static bool IsOverflow(ushort a_sr)
        {
            return Bits.IsSet(a_sr, BIT_OVERFLOW);
        }

        /// <summary>
        /// Overflow.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <param name="a_bitValue"></param>
        public static void SetOverflow(ref ushort a_sr, bool a_bitValue)
        {
            Bits.SetBit(ref a_sr, BIT_OVERFLOW, a_bitValue);
        }

        /// <summary>
        /// Carry.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <returns></returns>
        public static bool IsCarry(ushort a_sr)
        {
            return Bits.IsSet(a_sr, BIT_CARRY);
        }

        /// <summary>
        /// Carry.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <param name="a_bitValue"></param>
        public static void SetCarry(ref ushort a_sr, bool a_bitValue)
        {
            Bits.SetBit(ref a_sr, BIT_CARRY, a_bitValue);
        }

        /// <summary>
        /// Higher
        /// </summary>
        public static bool IsHI(ushort a_sr)
        {
            return (a_sr & (MASK_CARRY | MASK_ZERO)) == 0;
        }

        /// <summary>
        /// Lower or equal
        /// </summary>
        public static bool IsLS(ushort a_sr)
        {
            return (a_sr & (MASK_CARRY | MASK_ZERO)) != 0;
        }

        /// <summary>
        /// Carry clear
        /// </summary>
        public static bool IsCC(ushort a_sr)
        {
            return !IsCarry(a_sr);
        }

        /// <summary>
        /// High or equal
        /// </summary>
        public static bool IsHS(ushort a_sr)
        {
            return !IsCarry(a_sr);
        }

        /// <summary>
        /// Carry set
        /// </summary>
        public static bool IsCS(ushort a_sr)
        {
            return IsCarry(a_sr);
        }

        /// <summary>
        /// Lower than
        /// </summary>
        public static bool IsLO(ushort a_sr)
        {
            return IsCarry(a_sr);
        }

        /// <summary>
        /// Not equal
        /// </summary>
        public static bool IsNE(ushort a_sr)
        {
            return !IsZero(a_sr);
        }

        /// <summary>
        /// Equal
        /// </summary>
        public static bool IsEQ(ushort a_sr)
        {
            return IsZero(a_sr);
        }

        /// <summary>
        /// Overflow clear
        /// </summary>
        public static bool IsVC(ushort a_sr)
        {
            return !IsOverflow(a_sr);
        }

        /// <summary>
        /// Overflow set
        /// </summary>
        public static bool IsVS(ushort a_sr)
        {
            return IsOverflow(a_sr);
        }

        /// <summary>
        /// Plus
        /// </summary>
        public static bool IsPL(ushort a_sr)
        {
            return !IsNegative(a_sr);
        }

        /// <summary>
        /// ?Minus
        /// </summary>
        public static bool IsMI(ushort a_sr)
        {
            return IsNegative(a_sr);
        }

        /// <summary>
        /// Less than
        /// </summary>
        public static bool IsLT(ushort a_sr)
        {
            return IsNegative(a_sr) ^ IsOverflow(a_sr);
        }

        /// <summary>
        /// Greater of equal
        /// </summary>
        public static bool IsGE(ushort a_sr)
        {
            return !(IsNegative(a_sr) ^ IsOverflow(a_sr));
        }

        /// <summary>
        /// Greater than
        /// </summary>
        public static bool IsGT(ushort a_sr)
        {
            return !Bits.IsSet(a_sr, BIT_ZERO) &&
                !(Bits.IsSet(a_sr, BIT_NEGATIVE) ^ Bits.IsSet(a_sr, BIT_OVERFLOW));
        }

        /// <summary>
        /// Less or equal
        /// </summary>
        public static bool IsLE(ushort a_sr)
        {
            return IsZero(a_sr) || (IsNegative(a_sr) ^ IsOverflow(a_sr));
        }

        public static string Info(ushort a_sr)
        {
            return String.Format("X:{3}, N:{4}, Z:{5}, V:{6}, C:{7}",
                IsExtend(a_sr) ? "T" : "F", IsNegative(a_sr) ? "T" : "F", 
                IsZero(a_sr) ? "T" : "F", IsOverflow(a_sr) ? "T" : "F", 
                IsCarry(a_sr) ? "T" : "F");
        }
    }
}
